In the latter half of the twentieth century, there began a phenomenon known as the information revolution. While the information revolution is a historical development broader in scope than any one event or machine, no single device has come to represent the information revolution more than the digital electronic computer. The development of computer systems has surely been a revolution. Each year, computer systems grow faster, store more data, and provide more applications to their users. At the same time, the cost of computing resources has consistently declined, so that information which was too expensive to gather, store and process a few years ago, is no economically feasible to manipulate via computer. The reduced cost of information processing drives increasing productivity in a snowballing effect, because product designs, manufacturing processes, resource scheduling, administrative chores, and many other tasks, are made more efficient.
Early computer systems were isolated machines, in which data was input manually or from storage media and output generated to storage media or human perceptible form. While useful in their day, these systems were extremely limited in their ability to access and share information. As computers became more capable, and the ability to store vast amounts of digital data became prevalent, the desirability of communicating with other computer systems and sharing information became manifest. This demand for sharing information led to a growth of computer networks, including the Internet. It is now rare to find a general purpose computer system having no access to a network for communicating with other computer systems, although many special-purpose digital devices still operate in isolated environments.
More recently, this evolution of isolated computers to networked devices and shared information has proceeded to a further stage in digital data processing: the cloud. The “cloud” is in fact a collection of computing hardware and software resources which are accessible from remote locations to perform useful work on behalf of a client. However, except for the access point, such as a client computer terminal having limited capability, the client does not own or control hardware and software resources which provide computing services in the cloud. The cloud presents a virtualized system having the capability to provide whatever computing services are required. The client contracts to obtain the computing services. These services are provided by the virtualized system, i.e., without any specification of the particular physical computer systems which will provide the contracted service. This virtualization enables a provider of services in the cloud to re-allocate the physical computer resources as convenient, without involvement of the client. Cloud computing has thus been analogized to an electric utility, in which the customer purchases electric power without any knowledge or concern how the power is generated. Cloud computing not merely enables communications with other computing devices and access to remotely stored data, but enables the entire computing task to be performed remotely.
Although some of the concepts used in cloud computing date back to the 1950's and early time sharing systems, the use of cloud computing in a global networked environment is a relatively new phenomenon, and deployment of cloud computing on a broad scale is still in its early stages. New challenges arise as designers attempt to implement the broad concepts of cloud computing in functioning systems.
In both traditional and cloud computing systems, computer programs instruct the system to perform useful work. Programs are generally written in a high-level language. High-level languages vary in their characteristics, but all such languages are intended to make it easier for a human to write a program to perform some task. Typically, high-level languages represent operations, fixed values, variables, and other constructs in a manner readily understandable to the human programmer rather than the computer. Such programs are not directly executable by a computer's processor. In order to run on the computer, the programs must first be transformed from a human-readable form (source code) to something executable by a processor of a computer, i.e. to a set of instructions directly readable and executable by the processor, each comprising a respective sequence of binary bits in a pre-defined format, each bit position being specific to logic within a computer's processor which reads and decodes it. The bit sequence formatting and the meaning of the bit combinations defines the “instruction set” of the processor.
In general, source code is universal and understandable by anyone trained to use the applicable language, while executable code is specific to a particular computer system environment, and can only execute on that computer system or one similarly configured. In particular, the executable code is specific to the processor's instruction set, although it may be specific to other parameters of the computer system as well.
Various techniques exist for transforming the source code in a high-level language to processor-executable instructions in the processor's instruction set. Source code can be “interpreted”, meaning that a special program (an “interpreter”) takes each source code statement in sequence, and executes a small procedure (i.e., series of instructions in the processor-executable instruction set) corresponding to each source code instruction. Interpreting is useful for some purposes, but it is generally rather inefficient.
Traditionally, for greater execution efficiency, individual portions (modules) of source code are compiled to form modules of processor-executable instructions, which may be linked together to form larger programs (although some programs contain only a single compiled module). These programs are saved in digital media storage in executable form, and may be distributed in that form to other computer systems, or remain on the system in which they were first compiled. In this form they are later executed, usually many times. Compilation is itself a task performed by a special computer program (a compiler), and can take significant time. Often, compilation involves certain optimizations to the executable code which require analysis of the various instruction sequences within the program. Unlike interpreted code, the resultant processor-executable instructions in a compiled module do not necessarily correspond to particular source instructions, and do not necessarily follow the same sequence, although they must produce the same logical output. Since it is expected that such programs will be executed many times, the burden of compilation is spread over many executions. This traditional form of compilation is sometimes referred to as “static compilation”.
In recent years, there has been increasing interest in “just-in-time” dynamic compilation or optimization. Like static compilation, “just-in-time” or dynamic compilation/optimization involves the generation of optimized processor-executable instructions. But unlike static compilation, the program's processor-executable instructions are generated at the time of execution of the program of which the processor-executable instructions are a part (the “target program”). This effectively means that just-in-time or dynamic compilation/optimization is intended to be performed many times, for example, each time the program is executed, or for each user process which executes the program.
Obviously, when compared with traditional static compilation, dynamic compilation/optimization suffers from the drawback that it is performed again each time the program is executed or for each new user process. However, there are various advantages to just-in-time or dynamic compilation/optimization that make it attractive in many circumstances. For example, dynamically compiled code is generated on the system that will execute it, and can be generated from a universal, intermediate level code form (between a high-level source language and a processor-executable form), which facilitates portability of the program. Such an approach is frequently used in the well-known JAVA™ virtual machine environment. Furthermore, additional knowledge available to the system at execution time, such as the exact system configuration, the code modules being used, and the actual pattern of code execution, may make it possible to generate more efficient compiled code than can typically be generated using a static compiler. Such additional knowledge is particularly effective in the case of actual code usage patterns, which allow dynamic compilation/optimization to focus on optimizing specific portions of the code.
The advantage of portability inherent in dynamic compilation makes it particularly useful in many cloud computing environments, because the actual physical machine which will execute a given task is not generally known in advance, and hence the instruction set and other parameters of the processor or processors executing the task are unknown. A dynamic compiler can potentially generate the executable code at a time when the required binary instruction set format is known.
With the growth in cloud computing, it is desirable to adopt the compilation of computer programming code to a cloud environment in an optimal manner, and in particular to provide enhanced techniques for dynamic programming code compilation which take advantage of, and operate efficiently within, the cloud computing environment.